#!/bin/bash -
#===============================================================================
#          FILE: cbuild.sh
#         USAGE: ./cbuild.sh
#   DESCRIPTION:
#        AUTHOR: dengwei
#       CREATED: 07/31/2014 13:38
#      REVISION:  ---
#===============================================================================

BUILD_DIR=.cbuild
CMAKE_LISTFILE="CMakeLists.txt"
PRO_DIR=.
COMPILE_FLAG=0
CLEAN_FLAG=1
UNINSTALL_FLAG=2
INSTALL_FLAG=3
GET_ACTION=0
if [ -z "${MAKE_TOOL}" ] || ! hash ${MAKE_TOOL}; then
    MAKE_TOOL="make"
fi

CMAKE_ARG=" --no-warn-unused-cli"
if [ "${MAKE_TOOL}" == "ninja" ]; then
    CMAKE_ARG="${CMAKE_ARG} -GNinja"
fi
QUIET_FLAG=1
MYID=$(id -u)
RUSER=0
GUSER=0
corenum=0

function PUSHD()
{
    pushd $1 >/dev/null 2>/dev/null
}

function POPD()
{
    popd >/dev/null 2>/dev/null
}

function check_result()
{
    result=$1
    shift
    if [ ${result} -ne 0 ]; then
        echo -e "get result ${result} when $@, exit ..."
        exit ${result}
    fi
}

function cbuild_help()
{
    echo "Usage: $1 [-a (clean|install|uninstall)] [-d project_dir] [-v] [-g argument-for-cmake]"
    echo "       default action is only make"

    exit 0
}

function _get_cpu_num()
{
    if [ ! -f /tmp/.cpu_num ]; then
        lscpu | awk -F":" '($1 == "CPU(s)") {print int($2)}' >/tmp/.cpu_num
    fi
    cat /tmp/.cpu_num
}

function scmd()
{
    if [ ${MYID} -eq 0 ]; then
        eval $*
    else
        echo ${TERM} | awk 'BEGIN{IGNORECASE=1} ($1 == "dumb" || $1 == "unknown") {exit 1}'
        if [ $? -eq 0 ]; then
            eval sudo $*
        else
            script -eq -c "sudo $*" /dev/null
        fi
    fi
}

while getopts 'U:d:a:g:c:hv' opt; do
    case ${opt} in
        a)
            case ${OPTARG} in
                "clean") GET_ACTION=${CLEAN_FLAG};;
                "uninstall") GET_ACTION=${UNINSTALL_FLAG};;
                "install") GET_ACTION=${INSTALL_FLAG};;
                "compile") GET_ACTION=${COMPILE_FLAG};;
                ?|*) echo "action ${OPTARG} is invalid"; cbuild_help "$(basename $0)"; exit 1;;
            esac
            ;;
        c)
            corenum=${OPTARG}
            ;;
        d)
            if [ -d ${OPTARG} ]; then
                PRO_DIR=${OPTARG}
            else
                echo "the directory ${OPTARG} does not exist, exit ..."
                exit 1
            fi;;
        g)
            na=${OPTARG#*=}
            if [ "${na}" == "${OPTARG}" ] || [ $(grep -iEc "(on|off|true|false)" <<<"${na}") -gt 0 ]; then
                CMAKE_ARG=${CMAKE_ARG}" -D"${OPTARG}
            else
                CMAKE_ARG=${CMAKE_ARG}" -D"${OPTARG%%=*}"=\""${na}"\""
            fi
            ;;
        v)
            QUIET_FLAG=0
            ;;
        U)
            RUSER=$(id -u ${OPTARG} 2>/dev/null)
            if [ -z "${RUSER}" ]; then
                RUSER=0
            fi
            GUSER=$(id -g ${OPTARG})
            ;;
        h) cbuild_help "$(basename $0)"; exit 0;;
        ?) cbuild_help "$(basename $0)"; exit 1;;
    esac
done

if [ ${QUIET_FLAG} -eq 0 ]; then
    CMAKE_ARG=${CMAKE_ARG}" -DCMAKE_VERBOSE_MAKEFILE=on"
else
    CMAKE_ARG=${CMAKE_ARG}" -DCMAKE_VERBOSE_MAKEFILE=off"
fi

PUSHD ${PRO_DIR}
if [ ${GET_ACTION} -gt ${COMPILE_FLAG} ]; then
    if [ ! -d ${BUILD_DIR} ]; then
        echo "${BUILD_DIR} does not exist, exit ..."
        exit 1
    fi

    case ${GET_ACTION} in
        ${CLEAN_FLAG})
            echo "remove temporary files[${BUILD_DIR}] for ${PRO_DIR} ..."
            if [ -d ${BUILD_DIR} ]; then
                PUSHD ${BUILD_DIR}
                ${MAKE_TOOL} clean
                if [ $? -ne 0 ]; then
                    echo "Error when ${MAKE_TOOL} clean, but ignore it"
                fi
                POPD
            fi
            scmd rm -rf cbuild ${BUILD_DIR}
            ;;
        ${INSTALL_FLAG})
            echo "install action for ${PRO_DIR} ..."

            PUSHD ${BUILD_DIR}
            scmd ${MAKE_TOOL} install
            check_result $? ${MAKE_TOOL} install
            if [ ${RUSER} -gt 0 ] && [ -f install_manifest.txt ]; then
                scmd chown ${RUSER}:${GUSER} $(cat install_manifest.txt)
            fi
            POPD
            ;;
        ${UNINSTALL_FLAG})
            echo "uninstall action for ${PRO_DIR} ..."

            if [ -f ${BUILD_DIR}/install_manifest.txt ]; then
                PUSHD ${BUILD_DIR}
                while read -r line || [ -n "${line}" ]; do
                    echo "rm -f ${line}"
                    scmd rm -f "${line}"
                done <install_manifest.txt
                POPD
            else
                echo "No found build directory-${BUILD_DIR}, skip it."
            fi
            ;;
    esac
    exit 0
fi

####################
# only make below
####################
if [ ! -f ${CMAKE_LISTFILE} ]; then
    echo "${CMAKE_LISTFILE} does not exist, exit ..."
    exit 1
fi

if [ ! -d ${BUILD_DIR} ]; then
    mkdir ${BUILD_DIR}
fi

PUSHD ${BUILD_DIR}
echo cmake${CMAKE_ARG} ..
eval cmake${CMAKE_ARG} ..
result=$?
if [ ${result} -ne 0 ]; then
    echo -e "get result ${result} when cmake, exit ..."
    POPD
    rm -rf ${BUILD_DIR}
    exit ${result}
fi

CPU_NUM=""
if [ ${corenum} -eq 0 ]; then
    CPU_NUM=$(_get_cpu_num)
    (( CPU_NUM *= 4 ))
else
    CPU_NUM=${corenum}
fi
echo ${MAKE_TOOL} -j${CPU_NUM}
${MAKE_TOOL} -j${CPU_NUM}

check_result $? ${MAKE_TOOL}
POPD

exit 0
